package com.sxpi.course.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxpi.common.result.R;
import com.sxpi.common.utils.json.JsonUtil;
import com.sxpi.course.dto.CourseBuyDto;
import com.sxpi.course.dto.CourseDto;
import com.sxpi.course.pojo.Category;
import com.sxpi.course.pojo.Course;
import com.sxpi.course.service.category.ICategoryService;
import com.sxpi.course.service.course.ICourseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 董伟豪
 * @Date: 2022/10/13 13:21
 */
@RestController
@Slf4j
public class CourseController {

    @Autowired
    private ICourseService courseService;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 查询课程信息并分页搜索
     * @param courseDto
     * @return
     */
    @PostMapping("/course/page")
    public R findCoursePage(@RequestBody CourseDto courseDto){
        Page<Course> coursePage = courseService.findCoursePage(courseDto);
        return R.ok().put("coursePage",coursePage);
    }

    /**
     * 查询全部的分类
     * @return
     */
    @PostMapping("/course/category")
    public R findCategories(){
        List<Category> categories = categoryService.findCategories();
        return R.ok().put("categories",categories);
    }

    /**
     * 使用string的方式
     * 根据id查询出来的分类信息放入到缓存中
     * 如果高并发去访问一个不存在的id，那么我就创造一个空对象，防止缓存击穿
     * 可以更加容易修改缓存中的值
     * @param id
     * @return
     */
    @PostMapping("/course/get/{id}")
    public R getCourseDetail(@PathVariable("id")Long id){
        String courseKey = "course:cache:" + id;
        // java.util.LinkedHashMap cannot be cast to com.sxpi.course.pojo.Course
        Course course = (Course)redisTemplate.opsForValue().get(courseKey);
        if(course == null){
            course = courseService.getById(id);
            if(course == null){
                course = new Course();
            }
            redisTemplate.opsForValue().set(courseKey,course,600,TimeUnit.SECONDS);
        }
        // BeanUtil.beanToMap转换为map
        return R.ok().put("course", BeanUtil.beanToMap(course));
    }


    /**
     * 使用hash的方式
     * 根据id查询出来的分类信息放入到缓存中
     * 如果高并发去访问一个不存在的id，那么我就创造一个空对象，防止缓存击穿
     * 如果我写的是hash的话。我就很难去修改缓存中的值
     * 这种方式缺点没有过期时间，如果是特别爆火的商品可以采用这种方式
     * @param id
     * @return
     */
    @PostMapping("/course/gethash/{id}")
    @Deprecated
    public R getCourseHashDetail(@PathVariable("id")Long id){
        String redisKey = "course:cache:key";
        String courseKey = "course:cache:" + id;
        // java.util.LinkedHashMap cannot be cast to com.sxpi.course.pojo.Course
        Course course = (Course)redisTemplate.opsForHash().get(redisKey,courseKey);
        if(course == null){
            course = courseService.getById(id);
            Map<String,Object> courseMap = BeanUtil.beanToMap(course);
            if(courseMap == null){
                course = new Course();
            }
            // 在配置类中，我已经把对象转换成jackjson的字符串，course可以直接扔进去
            redisTemplate.opsForHash().put(redisKey,courseKey,course);
        }
        // BeanUtil.beanToMap转换为map
        return R.ok().put("course", BeanUtil.beanToMap(course));
    }

    /**
     * 根据id查询出来的分类信息放入到缓存中
     * @param id
     * @return
     */
    @PostMapping("/course/getdeprecated/{id}")
    @Deprecated
    public R getCourseDetailDeprecated(@PathVariable("id")Long id){
        String key = "course:detail:" + id;
        String jsonRedisTemplate = stringRedisTemplate.opsForValue().get(key);
        Course course = JsonUtil.string2Obj(jsonRedisTemplate, Course.class);
        if(course == null){
            course = courseService.getById(id);
            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(course),1, TimeUnit.DAYS);
        }
        // BeanUtil.beanToMap转换为map
        return R.ok().put("course", BeanUtil.beanToMap(course));
    }

    /**
     * 查询相关课程信息
     * @return
     */
    @PostMapping("/course/relation")
    public R findCoursePageRelation(@RequestBody CourseDto courseDto) {
        List<Course> courses = courseService.findCoursePageRelation(courseDto);
        return R.ok().put("courses",courses);
    }

    /**
     * 测试sentinel
     * @return
     */
    @PostMapping("/course/sentinel/test")
    public R findSentinelByZeroTest(){
        return R.ok(10 / 0);
    }

    /**
     * 购买商品扣减库存
     * @param courseBuyDto
     * @return
     */
    @PostMapping("/course/updatestore")
    public R miniusCourseStore(@RequestBody CourseBuyDto courseBuyDto){
        boolean flag = courseService.miniusCourseStore(courseBuyDto);
        return R.ok().put("flag",flag);
    }
}
